package org.os.framework.jpa;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;

/**
 * JPA 基础查询
 * 
 * @author weizuxiao
 */
@NoRepositoryBean
public interface BaseRepository<T extends BaseEntity, K>
        extends PagingAndSortingRepository<T, K>, JpaSpecificationExecutor<T> {

    /**
     * 根据ID查询
     * 
     * @param id 主键
     * @return
     */
    @SuppressWarnings("null")
    @Override
    @Transactional(readOnly = true)
    @Query(value = "select tb from #{#entityName} tb where tb.deleted = false and tb.id = ?1")
    Optional<T> findById(K id);

    /**
     * 根据ID判断是否存在
     * 
     * @param id 主键
     * @return
     */
    @SuppressWarnings("null")
    @Override
    default boolean existsById(K id) {
        return findById(id).isPresent();
    }

    /**
     * 查询所有
     * 
     * @return
     */
    @SuppressWarnings("null")
    @Override
    @Transactional(readOnly = true)
    @Query(value = "select tb from #{#entityName} tb where tb.deleted = false")
    Iterable<T> findAll();

    /**
     * 根据IDs查询
     * 
     * @param ids
     * @return
     */
    @SuppressWarnings("null")
    @Override
    @Transactional(readOnly = true)
    @Query("select tb from #{#entityName} tb where tb.deleted = false and id in ?1")
    Iterable<T> findAllById(Iterable<K> ids);

    /**
     * 统计
     * 
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    @Query("select count(1) from #{#entityName} tb where tb.deleted = false")
    long count();

    /**
     * 根据ID删除
     * 
     * @param id
     */
    @SuppressWarnings("null")
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Query("update #{#entityName} tb set tb.deleted = true where tb.id = ?1")
    @Modifying
    void deleteById(K id);

    /**
     * 删除实体
     * 
     * @param entity
     * 
     */
    @SuppressWarnings({ "unchecked", "null" })
    @Transactional(rollbackFor = Exception.class)
    default void delete(T entity) {
        if (null == entity) {
            return;
        }
        deleteById((K) entity.getId());
    }

    /**
     * 根据IDs删除
     * 
     * @param ids
     */
    @SuppressWarnings({ "unchecked", "null" })
    @Transactional(rollbackFor = Exception.class)
    default void deleteAll(Iterable<? extends T> ids) {
        ids.forEach(entity -> deleteById((K) entity.getId()));
    }

    /**
     * 删除所有
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Query("update #{#entityName} tb set tb.deleted = true")
    @Modifying
    void deleteAll();

}
